/**
 * 20220301:simplified from [UIComponent,ThreejsContainer]
 * 20220610:1.old canvas-ui has no practical use for now.
 *          2.compute rect width evets-area.
 * 20220614:1.change loading-ui name of closing-method.
 *          2.remove deprecated contructor.
 *          3.use VR-supporting dom-cross-platform-event.
 */
import React from 'react';
// import DOMCrossPlatformEvent from 'global-libs/event/dom-cross-platform-event';........20220614
import DOMCrossPlatformEvent from './dom-cross-platform-event';
import * as THREE from 'three';
import WEBGL from 'three/examples/jsm/capabilities/WebGL';//webGPU on the way
import assetsLoad from '../loader/assets-load';

/**extend event handles for THREE loader */
//#region
const THREE_LOADER_CONTAINER=[];
Object.defineProperty(THREE,'startLoad',{value:(msg)=>{
    THREE_LOADER_CONTAINER.forEach((container)=>{
        container.startLoad(msg);
    });
}});
Object.defineProperty(THREE,'loading',{value:(msg,prg)=>{
    THREE_LOADER_CONTAINER.forEach((container)=>{
        container.loading(msg,prg);
    });
}});
Object.defineProperty(THREE,'loadError',{value:(msg)=>{
    THREE_LOADER_CONTAINER.forEach((container)=>{
        container.loadError(msg);
    });
}});
Object.defineProperty(THREE,'loaded',{value:()=>{
    THREE_LOADER_CONTAINER.forEach((container)=>{
        container.loaded();
    });
}});
//#endregion

export default class ThreeContainer extends React.PureComponent {
    // constructor(props, context) {...................20220614
    //     super(props, context);
    //     this.initVariable();
    //     THREE_LOADER_CONTAINER.push(this);
    // }

    get ui(){}

    get loadingUI(){}

    resize(size){}

    startLoad(message){}

    loading(message,progress){}

    loadError(message){}

    loaded(){
        // if(window.loadingClose)window.loadingClose();.............20220614
        if(window.closeLoadingUI)window.closeLoadingUI();
    }

    get children() {
        return <React.Fragment>
            <div key="canvas_container" ref={this._canvasContainerRef=this._canvasContainerRef||React.createRef()}
                style={{position:'absolute',left:'0',right:'0',top:'0',bottom:'0',overflow:'hidden',lineHeight:'normal'}}/>
            <div key='event_area' ref={this._eventAreaRef=this._eventAreaRef||React.createRef()}
                style={{position:"absolute",left:"0px",top:"0px",width:"100%",height:"100%"}}/>
            {/* <div key="canvas_ui" style={{transform:"translateZ(1px)"}}></div>......................20220610 */}
            <div key="canvas_ui" style={{position:'absolute',left:'0',top:'0',width:'100%',height:'100%',pointerEvents:'none'}}>
                {this.ui} 
                {this.loadingUI} 
            </div>
            </React.Fragment>
    }

    get devicePixelRatio(){
        return Math.max(Math.min(window.devicePixelRatio,3),1);
    }

    initVariable() {
        this.renderer = null;
        this.crossEvent = null;
        this.size = null;
        this.clientRect = {};
        this.resizeChange = () => {
            let currentRect = {width: 0, height: 0, left: 0, right: 0, top: 0, bottom: 0};
            // if (this.refs.parent) {..........20220610
            if (this._eventAreaRef) {

                // let bound = this.refs.parent.getBoundingClientRect();.......20220610
                let bound = this._eventAreaRef.current.getBoundingClientRect();

                for (let k in currentRect) {
                    currentRect[k] = bound[k];
                }
            }
            let posChange = false;
            let sizeChange = false;
            if (currentRect.left !== this.clientRect.left || currentRect.top !== this.clientRect.top) {
                posChange = true;
            }
            if (currentRect.width !== this.clientRect.width || currentRect.height !== this.clientRect.height) {
                sizeChange = true;
            }
            if (!posChange && !sizeChange) {
                return;
            }
            this.clientRect = currentRect;
            this.clientRectChange(sizeChange, posChange);
        };
    }

    getRendererParameters(){
        return {};
    }
    getAssetsUrl(){
        return [];
    }
    initialize(){
        if(WEBGL.isWebGL2Available()){
            this.renderer = new THREE.WebGLRenderer(this.getRendererParameters());
        }else if(WEBGL.isWebGLAvailable()){
            this.renderer = new THREE.WebGL1Renderer(this.getRendererParameters());
        }else{
            alert("您的运行环境不支持WebGL！");
            return;
        }
        this.renderer.setPixelRatio(this.devicePixelRatio);
        this.renderer.setSize(this.size.width,this.size.height);
        this._canvasContainerRef.current.appendChild(this.renderer.domElement);
        this.resize(this.size);
        this.loadAssets();
    }

    loadAssets(){
        assetsLoad(this,this,this.getAssetsUrl).then(
            ()=>{
                this.initComponents(this.assetsLoader.assets);
                this.prepared();
                this.renderer.setAnimationLoop(this.animate.bind(this));
            },
            (err)=>{
                console.warn('failed to load assets!',err);
            }
        );
    }
    initComponents(){}
    prepared(){
    }
    animate(time,frame){
    }

    render() {
        return (
            <div {...this.props.orignalProps} ref='parent' >
                {this.children}
            </div>
        );
    }
   
    componentDidMount() {     
        this.initVariable();
        THREE_LOADER_CONTAINER.push(this);
        
        window.addEventListener("resize", this.resizeChange, {passive: false});
        window.addEventListener("scroll", this.resizeChange, true);
        this.resizeChange();
        document.oncontextmenu = ()=>{
            return false;
        };
        this.crossEvent = DOMCrossPlatformEvent.createEvent(this._eventAreaRef.current);
        this.crossEvent.start();
        this.initialize();
    }
    componentWillUnmount(){
        window.removeEventListener("resize", this.resizeChange);
        window.removeEventListener("scroll", this.resizeChange)
        this.clientRect = {};
        this.crossEvent.dispose();
        this.crossEvent = null;
    }

    clientRectChange(sizeChange,posChange){
        this.size = this._canvasContainerRef.current.getBoundingClientRect();
        try{
            this.renderer.setPixelRatio(window.devicePixelRatio);
            this.renderer.setSize(this.size.width, this.size.height);
            this.resize(this.size);
        }catch (ex){}
    }
  
}